package gzh.component;

import gzh.config.SpringContext;
import com.alibaba.fastjson.JSON;
import gzh.vo.Message;
import gzh.vo.ForbiddenWord;
import org.springframework.stereotype.Component;
import org.thymeleaf.util.StringUtils;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Component
@ServerEndpoint("/socket/{username}")
public class WebSocketServer {

    // 存储当前在线用户：用户名 -> Session
    public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
        if (StringUtils.isEmpty(username)) {
            System.out.println("拒绝连接：用户名为空");
            try {
                session.close(new CloseReason(CloseReason.CloseCodes.VIOLATED_POLICY, "Username cannot be empty"));
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }

        System.out.println("用户已连接: " + username);
        sessionMap.put(username, session);

        // 广播新用户加入 & 发送欢迎消息
        sendUserListUpdate();
        sendWelcomeMessage(username);
    }

    @OnClose
    public void onClose(@PathParam("username") String username) {
        System.out.println("用户已断开: " + username);
        sessionMap.remove(username);
        sendUserListUpdate(); // 更新用户列表
    }

    @OnMessage
    public void onMessage(String message) {
        try {
            Message msg = JSON.parseObject(message, Message.class);

            if (msg.getUserNames() != null) {
                return; // 系统消息直接忽略
            }

            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
            msg.setTime(sdf.format(new Date()));
            msg.setSystemMessage(false); // 普通消息

            // 获取所有敏感词
            List<String> forbiddenWords = SpringContext.getForbiddenWordRepo().getForbiddenWords();
            System.out.println("当前违禁词列表: " + forbiddenWords);

            // 判断是否包含违禁词
            boolean containsForbiddenWord = forbiddenWords.stream()
                .anyMatch(word -> word != null && !word.isEmpty() && msg.getContent().contains(word));

            if (containsForbiddenWord) {
                System.out.println("【拦截】发现敏感词，消息未发送");

                // 给发送者一个提示
                Message rejectMsg = new Message();
                rejectMsg.setFrom("系统");
                rejectMsg.setTo(msg.getFrom()); // 私发给发送者
                rejectMsg.setContent("你发送的消息包含敏感词，已被拦截");
                rejectMsg.setSystemMessage(true);
                rejectMsg.setTime(sdf.format(new Date()));

                sendMessage(JSON.toJSONString(rejectMsg), sessionMap.get(msg.getFrom()));
                return;
            }

            // 如果没有敏感词，正常转发消息
            if (!StringUtils.isEmpty(msg.getTo())) { // 私聊
                Session toSession = sessionMap.get(msg.getTo());
                if (toSession != null && toSession.isOpen()) {
                    sendMessage(JSON.toJSONString(msg), toSession);
                }
            } else { // 群发
                sendAllMessage(JSON.toJSONString(msg));
            }
        } catch (Exception e) {
            System.err.println("处理消息时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("WebSocket 发生错误");
        error.printStackTrace();
    }

    // 发送用户列表更新
    private void sendUserListUpdate() {
        List<String> userList = new ArrayList<>(sessionMap.keySet());
        Iterator<String> iterator = userList.iterator();
        while (iterator.hasNext()) {
            if (StringUtils.isEmpty(iterator.next())) {
                iterator.remove(); // 过滤掉空用户名
            }
        }
        System.out.println("发送用户列表: " + userList); // 添加日志
        Message systemMsg = new Message();
        systemMsg.setUserNames(userList);
        systemMsg.setSystemMessage(true);
        systemMsg.setContent("用户列表更新");
        sendAllMessage(JSON.toJSONString(systemMsg));
    }

    // 发送欢迎消息
    private void sendWelcomeMessage(String username) {
        Message welcomeMsg = new Message();
        welcomeMsg.setFrom("系统"); // 使用 from 字段
        welcomeMsg.setContent(username + " 加入了聊天室");
        welcomeMsg.setSystemMessage(true);
        welcomeMsg.setTime(new SimpleDateFormat("HH:mm").format(new Date()));
        sendAllMessage(JSON.toJSONString(welcomeMsg));
    }

    // 发送给单个用户
    private void sendMessage(String message, Session session) {
        try {
            if (session.isOpen()) {
                session.getBasicRemote().sendText(message);
                System.out.println("向 " + session.getId() + " 发送消息: " + message);
            }
        } catch (IOException e) {
            System.err.println("发送消息时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // 群发消息给所有用户
    public static void sendAllMessage(String message) {
        for (Session session : sessionMap.values()) {
            if (session.isOpen()) {
                try {
                    session.getBasicRemote().sendText(message);
                    System.out.println("向 " + session.getId() + " 群发消息: " + message);
                } catch (IOException e) {
                    System.err.println("群发消息时发生错误: " + e.getMessage());
                    e.printStackTrace();
                }
            }
        }
    }

    // 新增：广播违禁词更新
    // 修改广播违禁词更新方法

    public static void sendForbiddenWordsUpdate() {
        List<String> words = SpringContext.getForbiddenWordRepo().findAll().stream()
                .map(ForbiddenWord::getWord)
                .collect(Collectors.toList());

        Message msg = new Message();
        msg.setSystemMessage(true);
        msg.setContent("FORBIDDEN_WORDS_UPDATE");
        // 使用新的字段来传输违禁词列表
        msg.setForbiddenWords(words); // 确保你的 Message 类中有 setForbiddenWords 方法

        sendAllMessage(JSON.toJSONString(msg));
    }
}